<template>
  <div class="ai-assistant-container">
    <div class="page-header">
      <h1>AI 学习助手</h1>
      <p>智能问答，解决学习难题</p>
    </div>
    
    <div class="chat-container">
      <div class="chat-sidebar">
        <div class="history-header">
          <h3>历史对话</h3>
          <el-button type="primary" size="small" @click="createNewChat">
            <el-icon><Plus /></el-icon> 新对话
          </el-button>
        </div>
        
        <div class="chat-history">
          <div 
            v-for="(chat, index) in chatHistory" 
            :key="index"
            :class="['history-item', { active: currentChatId === chat.id }]"
            @click="selectChat(chat.id)"
          >
            <span class="chat-title">{{ chat.title }}</span>
            <span class="chat-time">{{ chat.time }}</span>
          </div>
        </div>
      </div>
      
      <div class="chat-main">
        <div class="message-list" ref="messageList">
          <div 
            v-for="(message, index) in currentMessages" 
            :key="index"
            :class="['message-item', message.role === 'assistant' ? 'ai-message' : 'user-message']"
          >
            <div class="message-avatar">
              <el-avatar :size="40" :src="message.role === 'assistant' ? aiAvatar : userAvatar"></el-avatar>
            </div>
            <div class="message-content">
              <div v-if="message.role === 'assistant'" v-html="formatMessage(message.content)"></div>
              <div v-else v-html="formatUserMessage(message.content)"></div>
              <div class="loading" v-if="message.loading">
                <div class="typing-indicator">
                  <span></span>
                  <span></span>
                  <span></span>
                </div>
              </div>
            </div>
          </div>
          
          <div v-if="isLoading && (!currentMessages.length || !currentMessages[currentMessages.length-1].loading)" class="message-item ai-message">
            <div class="message-avatar">
              <el-avatar :size="40" :src="aiAvatar"></el-avatar>
            </div>
            <div class="message-content">
              <div class="typing-indicator">
                <span></span>
                <span></span>
                <span></span>
              </div>
            </div>
          </div>
        </div>
        
        <div class="model-selector" v-if="modelList.length > 0">
          <h3>选择模型</h3>
          <el-select v-model="currentModel" placeholder="选择模型">
            <el-option
              v-for="model in modelList"
              :key="model"
              :label="model"
              :value="model"
            />
          </el-select>
        </div>
        
        <div class="message-input">
          <el-input
            v-model="userInput"
            type="textarea"
            :rows="3"
            placeholder="输入您的问题..."
            @keydown.enter.prevent="handleEnterKey"
          ></el-input>
          <div class="input-actions">
            <span class="input-tip">按 Enter 发送，Shift + Enter 换行</span>
            <el-button type="primary" @click="sendMessage" :disabled="!userInput.trim() || isLoading">
              发送
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, nextTick, watch } from 'vue';
import { useStore } from 'vuex';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { marked } from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/github.css';
// 导入 AI 聊天相关 API
import { getModelList, sendChatMessage } from '@/api/ai/chat';
// 导入 KaTeX 用于渲染 LaTeX 公式
import katex from 'katex';
import 'katex/dist/katex.min.css';

const store = useStore();
const userInput = ref('');
const isLoading = ref(false);
const messageList = ref(null);
const currentChatId = ref(null);
// 添加模型相关状态
const modelList = ref([]);
const currentModel = ref('');

// 配置 marked
marked.setOptions({
  highlight: function(code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(lang, code).value;
    }
    return hljs.highlightAuto(code).value;
  },
  breaks: true
});

// 添加 LaTeX 渲染扩展
const renderer = new marked.Renderer();
const originalCodeRenderer = renderer.code.bind(renderer);

renderer.code = function(code, language) {
  if (language === 'math' || language === 'latex') {
    try {
      return `<div class="math-block">${katex.renderToString(code, { displayMode: true })}</div>`;
    } catch (error) {
      console.error('LaTeX 渲染错误:', error);
      return `<pre><code class="error">LaTeX 渲染错误: ${error.message}</code></pre>`;
    }
  }
  return originalCodeRenderer(code, language);
};

// 添加行内 LaTeX 支持
const originalInlineCodeRenderer = renderer.codespan.bind(renderer);
renderer.codespan = function(code) {
  // 确保 code 是字符串
  if (typeof code === 'string' && code.startsWith('$') && code.endsWith('$')) {
    try {
      return katex.renderToString(code.slice(1, -1), { displayMode: false });
    } catch (error) {
      console.error('行内 LaTeX 渲染错误:', error);
      return `<code class="error">LaTeX 错误: ${error.message}</code>`;
    }
  }
  return originalInlineCodeRenderer(code);
};

marked.setOptions({ renderer });

// 头像
const userAvatar = 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png';
const aiAvatar = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png';

// 本地存储聊天历史
const chatHistory = ref([]);

// 获取当前对话的消息
const currentMessages = computed(() => {
  if (!currentChatId.value) return [];
  const chat = chatHistory.value.find(c => c.id === currentChatId.value);
  return chat ? chat.messages : [];
});

// 创建新对话
const createNewChat = () => {
  const newChatId = 'chat_' + Date.now();
  const newChat = {
    id: newChatId,
    title: '新对话',
    time: new Date().toLocaleString(),
    messages: []
  };
  
  chatHistory.value.unshift(newChat);
  currentChatId.value = newChatId;
  
  // 保存到本地存储
  saveChatsToLocalStorage();
};

// 选择对话
const selectChat = (chatId) => {
  currentChatId.value = chatId;
};

// 添加消息
const addMessage = (chatId, message) => {
  const chat = chatHistory.value.find(c => c.id === chatId);
  if (chat) {
    chat.messages.push(message);
    
    // 如果是用户消息且是对话的第一条消息，更新对话标题
    if (message.role === 'user' && chat.messages.length === 1) {
      updateChatTitle(chatId, message.content);
    }
    
    // 保存到本地存储
    saveChatsToLocalStorage();
  }
};

// 更新对话标题
const updateChatTitle = (chatId, title) => {
  const chat = chatHistory.value.find(c => c.id === chatId);
  if (chat) {
    chat.title = title.length > 20 ? title.substring(0, 20) + '...' : title;
    chat.time = new Date().toLocaleString();
    
    // 保存到本地存储
    saveChatsToLocalStorage();
  }
};

// 保存聊天记录到本地存储
const saveChatsToLocalStorage = () => {
  localStorage.setItem('aiChatHistory', JSON.stringify(chatHistory.value));
};

// 从本地存储加载聊天记录
const loadChatsFromLocalStorage = () => {
  const savedChats = localStorage.getItem('aiChatHistory');
  if (savedChats) {
    try {
      chatHistory.value = JSON.parse(savedChats);
    } catch (e) {
      console.error('加载聊天记录失败:', e);
      chatHistory.value = [];
    }
  }
};

// 发送消息
const sendMessage = async () => {
  if (!userInput.value.trim() || isLoading.value) return;
  
  if (!currentChatId.value) {
    createNewChat();
  }
  
  const userMessage = {
    role: 'user',
    content: userInput.value
  };
  
  // 添加用户消息
  addMessage(currentChatId.value, userMessage);
  
  userInput.value = '';
  isLoading.value = true;
  
  // 滚动到底部
  await nextTick();
  scrollToBottom();
  
  try {
    // 创建 AI 响应消息
    const aiResponse = {
      role: 'assistant',
      content: '',
      loading: true
    };
    
    // 添加 AI 响应（初始为空，带 loading 状态）
    addMessage(currentChatId.value, aiResponse);
    
    // 调用 API 发送消息
    sendChatMessage(
      {
        model: currentModel.value || modelList.value[0] || 'deepseek-r1:1.5b',
        message: userMessage.content
      },
      // 消息回调
      (data) => {
        try {
          console.log('收到的原始数据:', data);
          
          // 尝试解析返回的数据
          let content = '';
          
          // 检查数据是否包含 JSON 对象序列
          if (data.includes('{"content":')) {
            // 尝试提取所有 content 字段
            const contentMatches = data.match(/\{"content":"([^"]*)"\}/g);
            if (contentMatches) {
              for (const match of contentMatches) {
                try {
                  const parsed = JSON.parse(match);
                  if (parsed.content) {
                    content += parsed.content;
                  }
                } catch (e) {
                  console.warn('解析内容片段失败:', e);
                }
              }
            }
          } else {
            // 如果不是 JSON 格式，直接使用数据
            content = data;
          }
          
          console.log('提取的内容:', content);
          
          // 更新 AI 响应内容
          const chat = chatHistory.value.find(c => c.id === currentChatId.value);
          if (chat) {
            const aiMsg = chat.messages[chat.messages.length - 1];
            if (aiMsg && aiMsg.role === 'assistant') {
              aiMsg.content += content;
              saveChatsToLocalStorage();
              
              // 滚动到底部
              nextTick(() => {
                scrollToBottom();
              });
            }
          }
        } catch (e) {
          console.error('处理消息流失败:', e);
        }
      },
      // 错误回调
      (error) => {
        console.error('发送消息失败:', error);
        ElMessage.error('发送消息失败，请重试');
        
        // 移除 loading 状态
        const chat = chatHistory.value.find(c => c.id === currentChatId.value);
        if (chat) {
          const aiMsg = chat.messages[chat.messages.length - 1];
          if (aiMsg && aiMsg.role === 'assistant') {
            if (!aiMsg.content) {
              aiMsg.content = '抱歉，我遇到了一些问题，无法回答您的问题。请稍后再试。';
            }
            aiMsg.loading = false;
            saveChatsToLocalStorage();
          }
        }
        
        isLoading.value = false;
      },
      // 完成回调
      () => {
        // 移除 loading 状态
        const chat = chatHistory.value.find(c => c.id === currentChatId.value);
        if (chat) {
          const aiMsg = chat.messages[chat.messages.length - 1];
          if (aiMsg && aiMsg.role === 'assistant') {
            aiMsg.loading = false;
            saveChatsToLocalStorage();
          }
        }
        
        isLoading.value = false;
        
        // 滚动到底部
        nextTick(() => {
          scrollToBottom();
        });
      }
    );
  } catch (error) {
    console.error('发送消息失败:', error);
    ElMessage.error('发送消息失败，请重试');
    isLoading.value = false;
  }
};

// 格式化消息（将 markdown 转为 html，并处理思考部分和特殊标记）
const formatMessage = (content) => {
  // 移除 end 标记
  content = content.replace(/{"content":"end"}/, '');
  
  // 处理思考部分
  let processedContent = content.replace(/<think>([\s\S]*?)<\/think>/g, '<div class="thinking-content">$1</div>');
  
  // 处理行内 LaTeX 公式 (使用 $...$ 格式)
  processedContent = processedContent.replace(/\$([^\$\n]+?)\$/g, '`$$$1$$`');
  
  // 处理代码块，添加复制按钮和行号
  let htmlContent;
  try {
    htmlContent = marked(processedContent);
  } catch (error) {
    console.error('Markdown 渲染错误:', error);
    htmlContent = `<div class="error">Markdown 渲染错误: ${error.message}</div>` + 
                  `<div>${processedContent}</div>`;
  }
  
  // 为代码块添加复制按钮和行号
  htmlContent = htmlContent.replace(/<pre><code class="(.*?)">([\s\S]*?)<\/code><\/pre>/g, (match, language, codeContent) => {
    // 如果是 LaTeX 块，不添加行号
    if (language === 'math' || language === 'latex') {
      return match;
    }
    
    // 分割代码行
    const codeLines = codeContent.split('\n');
    
    // 生成行号HTML
    let lineNumbersHtml = '';
    for (let i = 1; i <= codeLines.length; i++) {
      lineNumbersHtml += `<span class="line-number">${i}</span>`;
    }
    
    // 返回带行号和复制按钮的代码块
    return `<div class="code-block-wrapper">
      <div class="line-numbers">${lineNumbersHtml}</div>
      <pre><code class="${language}">${codeContent}</code></pre>
      <button class="copy-btn" onclick="copyCode(this)"><i class="el-icon-document-copy"></i>复制</button>
    </div>`;
  });
  
  return htmlContent;
};

// 复制代码功能
const copyCode = (button) => {
  const codeBlock = button.previousElementSibling.querySelector('code');
  const textToCopy = codeBlock.textContent;
  
  navigator.clipboard.writeText(textToCopy)
    .then(() => {
      ElMessage.success('代码已复制到剪贴板');
    })
    .catch(err => {
      ElMessage.error('复制失败: ' + err);
    });
};

// 将复制函数暴露给全局，以便内联事件可以调用
window.copyCode = copyCode;

// 滚动到底部
const scrollToBottom = () => {
  if (messageList.value) {
    messageList.value.scrollTop = messageList.value.scrollHeight;
  }
};

// 获取模型列表
const fetchModelList = async () => {
  try {
    const res = await getModelList();
    if (res && res.data) {
      modelList.value = res.data;
      console.log('获取到的模型列表:', modelList.value);
      if (modelList.value.length > 0) {
        currentModel.value = modelList.value[0];
      }
    }
  } catch (error) {
    console.error('获取模型列表失败:', error);
    ElMessage.error('获取模型列表失败，将使用默认模型');
  }
};

// 监听当前对话变化，滚动到底部
watch(currentMessages, () => {
  nextTick(() => {
    scrollToBottom();
  });
});

// 组件挂载时，加载聊天历史和模型列表
onMounted(async () => {
  // 加载聊天历史
  loadChatsFromLocalStorage();
  
  if (chatHistory.value.length > 0) {
    currentChatId.value = chatHistory.value[0].id;
  } else {
    createNewChat();
  }
  
  // 获取模型列表
  await fetchModelList();
  
  nextTick(() => {
    scrollToBottom();
  });
});

// 处理回车键
const handleEnterKey = (event) => {
  // 如果按下了 Shift 键，则允许换行
  if (event.shiftKey) {
    // 手动在光标位置插入换行符
    const textarea = event.target;
    const start = textarea.selectionStart;
    const end = textarea.selectionEnd;
    const value = textarea.value;
    
    // 在光标位置插入换行符
    userInput.value = value.substring(0, start) + '\n' + value.substring(end);
    
    // 设置新的光标位置
    nextTick(() => {
      textarea.selectionStart = textarea.selectionEnd = start + 1;
    });
    
    return;
  }
  
  // 如果没有按下 Shift 键，则发送消息
  if (!isLoading.value && userInput.value.trim()) {
    sendMessage();
  }
};

// 格式化用户消息（将普通文本转为 html）
const formatUserMessage = (content) => {
  // 转义HTML特殊字符，防止XSS攻击
  const escapedContent = content
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
  
  // 将换行符转换为<br>标签
  return escapedContent.replace(/\n/g, '<br>');
};
</script>

<style lang="scss" scoped>
.ai-assistant-container {
  padding: 20px;
  max-width: 90%;
  margin: 0 auto;
  
  .page-header {
    margin-bottom: 20px;
    
    h1 {
      margin: 0 0 10px;
      font-size: 24px;
      color: #303133;
    }
    
    p {
      margin: 0;
      color: #606266;
      font-size: 14px;
    }
  }
  
  .chat-container {
    display: flex;
    height: calc(100vh - 150px);
    border: 1px solid #ebeef5;
    border-radius: 4px;
    overflow: hidden;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    
    .chat-sidebar {
      width: 250px;
      min-width: 250px; /* 添加最小宽度，防止被挤压 */
      display: flex;
      flex-direction: column;
      background-color: #f5f7fa;
      border-right: 1px solid #e6e6e6;
      
      .history-header {
        padding: 15px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid #e6e6e6;
        
        h3 {
          margin: 0;
          font-size: 16px;
        }
      }
      
      .chat-history {
        flex: 1;
        overflow-y: auto;
        
        .history-item {
          padding: 12px 15px;
          cursor: pointer;
          border-bottom: 1px solid #ebeef5;
          transition: background-color 0.3s;
          
          &:hover {
            background-color: #ecf5ff;
          }
          
          &.active {
            background-color: #ecf5ff;
            border-right: 3px solid #409eff;
          }
          
          .chat-title {
            display: block;
            font-size: 14px;
            color: #303133;
            margin-bottom: 5px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .chat-time {
            font-size: 12px;
            color: #909399;
          }
        }
      }
    }
    
    .chat-main {
      flex: 1;
      display: flex;
      flex-direction: column;
      background-color: #fff;
      
      .message-list {
        flex: 1;
        overflow-y: auto;
        padding: 20px;
        
        .message-item {
          display: flex;
          margin-bottom: 20px;
          
          .message-avatar {
            margin-right: 12px;
            flex-shrink: 0;
          }
          
          .message-content {
            max-width: 85%;
            padding: 12px 16px;
            border-radius: 8px;
            font-size: 14px;
            line-height: 1.5;
            word-break: break-word;
            
            :deep(pre) {
              background-color: #f5f7fa;
              padding: 10px;
              border-radius: 4px;
              overflow-x: auto;
            }
            
            :deep(code) {
              font-family: Consolas, Monaco, 'Andale Mono', monospace;
            }
            
            :deep(p) {
              margin: 8px 0;
            }
            
            :deep(ul, ol) {
              padding-left: 20px;
            }
            
            .loading {
              margin-top: 8px;
            }
            
            :deep(.thinking-content) {
              font-size: 12px;
              color: #909399;
              background-color: #f8f8f8;
              padding: 8px;
              border-radius: 4px;
              margin: 8px 0;
              border-left: 3px solid #dcdfe6;
            }
            
            :deep(.math-block) {
              overflow-x: auto;
              padding: 8px 0;
            }
            
            :deep(.code-block-wrapper) {
              position: relative;
              margin: 16px 0;
              display: flex;
              
              .line-numbers {
                display: flex;
                flex-direction: column;
                padding: 16px 8px;
                background-color: #e8e8e8;
                border-radius: 4px 0 0 4px;
                text-align: right;
                user-select: none;
                
                .line-number {
                  font-size: 12px;
                  color: #909399;
                  line-height: 24px;
                  height: 24px;
                }
              }
              
              pre {
                flex: 1;
                background-color: #f0f2f5;
                padding: 16px;
                border-radius: 0 4px 4px 0;
                overflow-x: auto;
                margin: 0;
                border: 1px solid #e4e7ed;
                border-left: none;
                
                code {
                  line-height: 24px;
                }
              }
              
              .copy-btn {
                position: absolute;
                top: 5px;
                right: 5px;
                background-color: rgba(64, 158, 255, 0.1);
                color: #409eff;
                border: none;
                border-radius: 4px;
                padding: 4px 8px;
                font-size: 12px;
                cursor: pointer;
                display: flex;
                align-items: center;
                gap: 4px;
                opacity: 0;
                transition: opacity 0.3s;
                
                &:hover {
                  background-color: rgba(64, 158, 255, 0.2);
                }
              }
              
              &:hover .copy-btn {
                opacity: 1;
              }
            }
          }
          
          &.user-message {
            flex-direction: row-reverse;
            
            .message-avatar {
              margin-right: 0;
              margin-left: 12px;
            }
            
            .message-content {
              background-color: #ecf5ff;
              color: #303133;
            }
          }
          
          &.ai-message {
            .message-content {
              background-color: #f5f7fa;
              color: #303133;
            }
          }
        }
        
        .typing-indicator {
          display: flex;
          align-items: center;
          
          span {
            height: 8px;
            width: 8px;
            border-radius: 50%;
            background-color: #909399;
            margin: 0 2px;
            display: inline-block;
            animation: typing 1.5s infinite ease-in-out;
            
            &:nth-child(1) {
              animation-delay: 0s;
            }
            
            &:nth-child(2) {
              animation-delay: 0.2s;
            }
            
            &:nth-child(3) {
              animation-delay: 0.4s;
            }
          }
        }
      }
      
      /* 将模型选择器移到输入框上方 */
      .model-selector {
        padding: 10px 15px;
        border-top: 1px solid #e6e6e6;
        
        h3 {
          margin: 0 0 10px;
          font-size: 14px;
        }
        
        .el-select {
          width: 100%;
        }
      }
      
      .message-input {
        padding: 15px;
        border-top: 1px solid #ebeef5;
        
        .input-actions {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-top: 10px;
          
          .input-tip {
            font-size: 12px;
            color: #909399;
          }
        }
      }
    }
  }
}

@keyframes typing {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
  100% {
    transform: translateY(0);
  }
}

@media (max-width: 768px) {
  .chat-container {
    flex-direction: column;
    height: calc(100vh - 150px);
    
    .chat-sidebar {
      width: 100%;
      height: 200px;
    }
  }
}
</style> 